package org.enhance.core.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Pattern;

/**
 * ip工具类
 *
 * @author wenpanfeng 2022/12/14 20:19
 */
@Slf4j
public class IpUtils {
    /**
     * 判断是否ip的正则表达式
     */
    private static final Pattern IP_PATTERN = Pattern.compile("^(([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5]))).)(([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5]))).){2}([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5])))$");

    /**
     * 私有构造函数,防止实例化
     */
    private IpUtils() {
    }

    /**
     * 获取本机ip
     *
     * @return 本机ip
     */
    public static String getLocalIp() {
        try {
            InetAddress address = InetAddress.getLocalHost();
            return address.getHostAddress().toString();
        } catch (UnknownHostException e) {
            log.error("get local ip error!", e);
        }
        return null;
    }

    /**
     * 枚举网卡,获取本机所有ip
     *
     * @return 本机所有ip
     */
    public static List<String> getLocalIpList() {
        try {
            List<String> addressList = new ArrayList<>();
            Enumeration<NetworkInterface> theIntfList = NetworkInterface.getNetworkInterfaces();
            while (theIntfList.hasMoreElements()) {
                NetworkInterface ifc = theIntfList.nextElement();
                log.debug("eth info:{},{}", ifc.getDisplayName(), ifc.isUp());
                if (ifc.isUp()) {
                    Enumeration<InetAddress> addresses = ifc.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        InetAddress address = addresses.nextElement();
                        String ip = address.getHostAddress().toString();
                        log.debug("ip info:{}, {}", ifc.getDisplayName(), ip);
                        if (isIp(ip)) {
                            addressList.add(ip);
                        }
                    }
                }
            }
            if (addressList.isEmpty()) {
                log.warn("ip list is empty");
                String localIp = IpUtils.getLocalIp();
                if (StringUtils.isNotBlank(localIp)) {
                    addressList.add(localIp);
                }
            }
            return addressList;
        } catch (SocketException e) {
            log.error("get local ip error!", e);
        }
        return new ArrayList<>();
    }

    /**
     * 从http request中获取客户端ip
     *
     * @param request http reqeust
     * @return 客户端ip
     */
    public static String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (isIpNotExist(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }

        if (isIpNotExist(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }

        if (isIpNotExist(ip)) {
            ip = request.getHeader("X-Real-IP");
        }

        if (isIpNotExist(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * ip 是否存在
     *
     * @param ip ip
     * @return 是否是ip
     */
    private static boolean isIpNotExist(String ip) {
        return StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip);
    }

    /**
     * 是否是正确的IPx形式
     *
     * @param ip ip
     */
    public static boolean isIp(String ip) {
        return IP_PATTERN.matcher(ip).matches();
    }
}